#include<stdio.h>
//#include<Mesh/Mesh_Frame.h>
//#include<Mesh/lib_cell_Iterator.h>
#include<Mesh_IO/Mesh_IO.h>
//#include<Algorithm/Algorithm1.h>
//#include<Algorithm/Algorithm2.h>
#include<tool/libcell_tools_formats.h>
#include<tool/libcell_tools_view.h>
//#include<Algorithm/Harmonic.h>
//#include <Algorithm/Conformal.h>
#include<tool/libcell_tools_octree.h>
#include<tool/libcell_tools_algorithm.h>
#include<Mesh/libcell_iterator.h>
#include <Algorithm/qem.h>
#include<Algorithm/points_cloud_algorithm.h>
#include<libcell_macros.h>

#define _ReadOff_   LibCell_ReadOff_
#define _ReadCell_  LibCell_ReadCell_
#define _ReadPly_ LibCell_ReadPly_
#define _WriteOff_ LibCell_WriteOff_

#define _WriteCell_ LibCell_WriteCell_

static double compute_triangle_energyn(template_v* v1,
    template_v* v2,
    template_v* v3)
{
    double a= distance_of_two_points(v2->point,v3->point,3),
        b= distance_of_two_points(v1->point,v3->point,3),
        c= distance_of_two_points(v1->point,v2->point,3);

    double cosa = (b*b+c*c-a*a)/(2*b*c);
    double cosb = (a*a+c*c-b*b)/(2*a*c);


    double anglea = acos(cosa) , angleb = acos(cosb);

    return (anglea>=angleb?anglea:angleb);
}


typedef struct Suture_Vertex{
    // 0 是上 ,1是下
    int shang_or_xia;
    int i;
    template_v* v;
}Suture_Vertex;

static inline void suture_vertex_init(Suture_Vertex*sv)
{
    sv->shang_or_xia=0;
    sv->i=0;
    sv->v=NULL;
}

// is_loop： vb1和vb2 是否构成loop
// 
Node* libcell_tools_suture_two_boundarries(template_v** vb11,int len1,
    template_v** vb22,int len2,
    int* vb1_index,int index_len1,
    int* vb2_index,int index_len2,
    int is_loop)
{
    Node* re=NULL;
    int wei1=0,wei2=0;
    // int len1=0,len2=0;

    double temp_dis=distance_of_two_points(vb11[vb1_index[wei1] ]->point,
        vb22[vb2_index[wei2]]->point,3);
    for(int i=1;i<len2;i++)
    {
        double temp_dis1=distance_of_two_points(vb11[vb1_index[wei1] ]->point,
            vb22[vb2_index[i]] ->point,3);
        if(temp_dis1<temp_dis)
        {
            temp_dis=temp_dis1;
            wei2=i;
        }
    }

    printf("len1:%d len2:%d\n",len1,len2);

    int i=0,j=0;
    int thre_len1=index_len1,thre_len2=index_len2;
    if(!is_loop)
    {
        thre_len1--;
        thre_len2--;
    }
    while(i<thre_len1||j<thre_len2)
    {

        // template_v**vs=(template_v**)malloc(sizeof(template_v*)*3);
        Suture_Vertex*vs=(Suture_Vertex*)malloc(sizeof(Suture_Vertex)*3);
        // if(node_size(re)>=50){break;}

        re=node_overlying(re,vs);
        vs[0].shang_or_xia=0;
        vs[0].i=vb1_index[((wei1+i)%index_len1)];
        vs[0].v=vb11[vs[0].i];

        // vs[0]=vb11[((wei1+i)%len1)];
        vs[1].shang_or_xia=1;
        vs[1].i=vb2_index[((wei2+j)%index_len2)];
        vs[1].v=vb22[vs[1].i];
        // printf("wei1:%d wei2:%d\n",wei1,wei2);
        if(i<thre_len1)
        {
            if(j<thre_len2)
            {
                double ener1=compute_triangle_energyn(
                    vs[0].v,vs[1].v,vb11[vb1_index[((wei1+i+1)%index_len1)]]);
                double ener2=compute_triangle_energyn(
                    vs[0],vs[1],vb22[vb2_index[((wei2+j+1)%index_len2)]]);
                
                if(ener1<ener2)
                {
                    vs[2].shang_or_xia=0;
                    vs[2].i=vb1_index[(wei1+i+1)%index_len1];
                    vs[2].v=vb11[vs[2].i];
                    // vs[2] = vb11[((wei1+i+1)%len1)];
                    // printf("%d %d vb11:%d\n",vs[0]->id,vs[1]->id,vs[2]->id );
                    i++;
                }
                else
                {
                    vs[2].shang_or_xia=1;
                    vs[2].i=vb2_index[((wei2+j+1)%index_len2)];
                    vs[2].v=vb22[vs[2].i];
                    // vs[2] = vb22[((wei2+j+1)%len2)];
                    // printf("%d %d vb22:%d\n",
                    //     vs[0]->id,vs[1]->id,vs[2]->id );
                    j++;
                }
            }
            else
            {
                vs[2].shang_or_xia=0;
                vs[2].i=vb1_index[(wei1+i+1)%index_len1];
                vs[2].v=vb11[vs[2].i];
                // vs[2] = vb11[((wei1+i+1)%len1)] ;
                // printf("%d %d vb11:%d\n",vs[0]->id,vs[1]->id,vs[2]->id );

                i++;
            }
        }
        else
        {
            vs[2].shang_or_xia=1;
            vs[2].i=vb2_index[((wei2+j+1)%index_len2)];
            vs[2].v=vb22[vs[2].i];
            // vs[2] = vb22[((wei2+j+1)%len2)];
            // printf("%d %d vb22:%d\n",
            //             vs[0]->id,vs[1]->id,vs[2]->id );
            j++;
        }
        // printf("%d %d %d",)
        // printf("i:%d j:%d\n",i,j);
    }

    return re;
}


static void libcell_fill_vb_index_according_sampling_dis(
    template_v**vb,int len,double sampling_dis,
    int* vb_index,int* index_len)
{
    *index_len=0;
    if(vb==NULL||len<=0){return;}
    int i=0;
    while(i<len)
    {
        vb_index[*index_len]=i;
        *index_len=1+*index_len;
        i++;
        for(;i<len;i++)
        {
            double dis=distance_of_two_points(
                vb[vb_index[*index_len-1]]->point,
                vb[i]->point,3);
            if(dis>=sampling_dis)
            {
                break;
            }  
        }
    }
}

// 新版本的缝合边界，会对边界进行重采样
// sampling_dis :采样距离
// 
Node* libcell_tools_suture_two_boundarriesn(Node* vb1,
    Node* vb2,int is_loop,double sampling_dis)
{

    int len1=0,len2=0;
    template_v**vb11=(template_v**)node2array(vb1,&len1);
    
    template_v**vb22=(template_v**)node2array(vb2,&len2);

    int* vb1_index=(int*)malloc(sizeof(int)*len1);
    memset(vb1_index,0,sizeof(int)*len1);

    int* vb2_index=(int*)malloc(sizeof(int)*len2);
    memset(vb2_index,0,sizeof(int)*len2);

    int index_len1=0,index_len2=0;
    libcell_fill_vb_index_according_sampling_dis(
        vb11,len1,sampling_dis,
        vb1_index,&index_len1);
    libcell_fill_vb_index_according_sampling_dis(
        vb22,len2,sampling_dis,
        vb2_index,&index_len2);
    Node* re=NULL;


    



    free(vb1_index);free(vb2_index);

    free(vb11);free(vb22);
    return re;
}

int main()
{
    Mesh m1,m2;
    Mesh_init(&m1);Mesh_init(&m2);

    _ReadOff_(&m1 ,"vb1.off" ,3);
    _ReadOff_(&m2 ,"vb2.off" ,3);
    Node* vb1=NULL,*vb2=NULL;
    for(auto vit=m1.v_begin(&m1);vit!=m1.v_end(&m1);vit++)
    {
        // vb1=node_overlying(vb1,quote(vit));
        vb1=node_pushback(vb1,quote(vit));
        // printf("%lf %lf %lf\n",quote(vit)->point[0],
        //     quote(vit)->point[1],
        //     quote(vit)->point[2]);
    }
    printf("vb1 nums:%d %d\n",m1.num_v(&m1),((template_v*)(vb1->value))->id );
    vb1=node_reverse(vb1);
    printf("vb2\n");

    for(auto vit=m2.v_begin(&m2);vit!=m2.v_end(&m2);vit++)
    {
        // vb2=node_overlying(vb2,quote(vit));
        vb2=node_pushback(vb2,quote(vit));
        // printf("%lf %lf %lf\n",quote(vit)->point[0],
        //     quote(vit)->point[1],
        //     quote(vit)->point[2]);
    }
    printf("vb2 nums:%d %d\n",m2.num_v(&m2),((template_v*)(vb2->value))->id );

    vb2=node_reverse(vb2);

    // Node*tris= libcell_tools_suture_two_boundarries(vb1,vb2,1);
    
    
    // Mesh* m=(Mesh*)malloc(sizeof(Mesh));
    // Mesh_init(m);

    // m->dimension=2;m->simplex=1;m->manifold_require=1;
    // for(Node* nit=tris;nit!=NULL;nit=(Node*)(nit->Next))
    // {
    //     template_v**vs=(template_v**)(nit->value);
    //     template_v*vs1[3]={0};
    //     vs1[0]=m->create_vertexv(m,vs[0]->point,3);
    //     vs1[1]=m->create_vertexv(m,vs[1]->point,3);
    //     vs1[2]=m->create_vertexv(m,vs[2]->point,3);
    //     m->create_cellv(m,vs1,3);
    // }


    // _WriteOff_(m,"ce.off");


    return 0;
}